// Package main 是应用程序的入口点
// 用户行为边界检查服务(UBBC - User Behavior Boundary Check)
// 提供基于豆包AI的图片内容合规性检查RESTful API服务
package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"ubbc/internal/config"
	"ubbc/internal/handler"
	"ubbc/internal/interfaces"
	"ubbc/internal/service"
	"ubbc/pkg/client"
	"ubbc/pkg/logger"
)

const (
	// 默认配置文件路径
	defaultConfigPath = "config.json"
	defaultRulesPath  = "ubbc-rules.json"

	// 应用信息
	appName    = "UBBC Server"
	appVersion = "1.0.0"
)

func main() {
	fmt.Printf("%s v%s starting...\n", appName, appVersion)

	// 加载配置文件
	cfg, err := loadConfiguration()
	if err != nil {
		fmt.Printf("Failed to load configuration: %v\n", err)
		os.Exit(1)
	}

	// 初始化日志记录器
	log := logger.New(cfg.Logging.Level, cfg.Logging.Format)
	log.Info("Application starting", "", map[string]interface{}{
		"app_name":    appName,
		"app_version": appVersion,
		"config_file": defaultConfigPath,
		"rules_file":  defaultRulesPath,
	})

	// 加载检查规则
	rules, err := config.LoadRules(defaultRulesPath)
	if err != nil {
		log.Fatal("Failed to load rules", "", map[string]interface{}{
			"error":      err.Error(),
			"rules_file": defaultRulesPath,
		})
	}
	log.Info("Rules loaded successfully", "", map[string]interface{}{
		"rules_count": len(rules),
	})

	// 初始化图片内容分析客户端
	var imageModelClient interfaces.ImageModelClientInterface
	switch cfg.ActiveModel {
	case "ollama":
		imageModelClient = client.NewOllamaClient(&cfg.Ollama, log, rules)
		log.Info("Ollama client initialized", "", map[string]interface{}{
			"api_url": cfg.Ollama.APIURL,
			"model":   cfg.Ollama.Model,
			"timeout": cfg.Ollama.Timeout.String(),
		})
	case "lmstudio":
		imageModelClient = client.NewLMStudioClient(&cfg.LMStudio, log, rules)
		log.Info("LM Studio client initialized", "", map[string]interface{}{
			"api_url": cfg.LMStudio.APIURL,
			"model":   cfg.LMStudio.Model,
			"timeout": cfg.LMStudio.Timeout.String(),
		})
	case "doubao":
		fallthrough
	default:
		imageModelClient = client.NewDoubaoClient(&cfg.Doubao, log, rules)
		log.Info("Doubao client initialized", "", map[string]interface{}{
			"api_url": cfg.Doubao.APIURL,
			"model":   cfg.Doubao.Model,
			"timeout": cfg.Doubao.Timeout.String(),
		})
	}

	// 初始化检查服务
	checkService := service.NewCheckService(cfg, rules, imageModelClient, log)
	log.Info("Check service initialized", "", map[string]interface{}{
		"cache_enabled": cfg.Cache.Enabled,
		"cache_ttl":     cfg.Cache.TTL.String(),
		"max_workers":   cfg.Concurrency.MaxWorkers,
	})

	// 初始化HTTP处理器
	checkHandler := handler.NewCheckHandler(cfg, checkService, log)

	// 设置HTTP服务器
	server := setupHTTPServer(cfg, checkHandler, log)

	// 启动服务器前输出启动提示
	fmt.Printf("\n[%s] %s[INFO]%s : ubbc serv 启动: http://%s:%s\n", time.Now().Format("2006-01-02 15:04:05"), "\033[32m", "\033[0m", cfg.Server.Host, cfg.Server.Port)

	// 启动服务器
	go func() {
		log.Info("HTTP server starting", "", map[string]interface{}{
			"host":        cfg.Server.Host,
			"port":        cfg.Server.Port,
			"tls_enabled": cfg.Security.TLSEnabled,
		})

		var err error
		if cfg.Security.TLSEnabled {
			err = server.ListenAndServeTLS(cfg.Security.CertFile, cfg.Security.KeyFile)
		} else {
			err = server.ListenAndServe()
		}

		if err != nil && err != http.ErrServerClosed {
			log.Fatal("HTTP server failed", "", map[string]interface{}{
				"error": err.Error(),
			})
		}
	}()

	log.Info("Server started successfully", "", map[string]interface{}{
		"listen_address": fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port),
		"endpoints": []string{
			"/api/v1/check-image",
			"/health",
		},
	})

	// 等待关闭信号
	waitForShutdown(server, log)
}

// loadConfiguration 加载应用配置
// 从配置文件中读取并验证配置信息
func loadConfiguration() (*config.Config, error) {
	cfg, err := config.LoadConfig(defaultConfigPath)
	if err != nil {
		return nil, fmt.Errorf("failed to load config: %w", err)
	}

	// 验证必要的配置项
	if cfg.Doubao.APIKey == "" {
		return nil, fmt.Errorf("doubao API key is required")
	}

	return cfg, nil
}

// setupHTTPServer 设置HTTP服务器
// 配置服务器参数、路由和中间件
func setupHTTPServer(cfg *config.Config, checkHandler *handler.CheckHandler, log *logger.Logger) *http.Server {
	// 设置路由
	mux := checkHandler.SetupRoutes()

	// 创建HTTP服务器
	server := &http.Server{
		Addr:         fmt.Sprintf("%s:%s", cfg.Server.Host, cfg.Server.Port),
		Handler:      corsMiddleware(securityMiddleware(mux, log)),
		ReadTimeout:  cfg.Server.ReadTimeout.ToDuration(),
		WriteTimeout: cfg.Server.WriteTimeout.ToDuration(),
		IdleTimeout:  cfg.Server.IdleTimeout.ToDuration(),
	}

	return server
}

// corsMiddleware CORS中间件
// 设置跨域资源共享头
func corsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 设置CORS头
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key")
		w.Header().Set("Access-Control-Max-Age", "3600")

		// 处理预检请求
		if r.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
			return
		}

		next.ServeHTTP(w, r)
	})
}

// securityMiddleware 安全中间件
// 添加安全相关的HTTP头
func securityMiddleware(next http.Handler, log *logger.Logger) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 设置安全头
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.Header().Set("X-Frame-Options", "DENY")
		w.Header().Set("X-XSS-Protection", "1; mode=block")
		w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")

		// 记录安全事件（如果需要）
		if suspiciousRequest(r) {
			log.Warn("Suspicious request detected", "", map[string]interface{}{
				"method":      r.Method,
				"url":         r.URL.String(),
				"user_agent":  r.Header.Get("User-Agent"),
				"remote_addr": r.RemoteAddr,
			})
		}

		next.ServeHTTP(w, r)
	})
}

// suspiciousRequest 检查是否是可疑请求
// 简单的安全检查逻辑
func suspiciousRequest(r *http.Request) bool {
	userAgent := r.Header.Get("User-Agent")

	// 检查是否缺少User-Agent
	if userAgent == "" {
		return true
	}

	// 可以添加更多的安全检查逻辑
	// 例如：检查恶意User-Agent、SQL注入模式等

	return false
}

// waitForShutdown 等待关闭信号并优雅关闭服务器
// 监听系统信号，实现优雅关闭
func waitForShutdown(server *http.Server, log *logger.Logger) {
	// 创建信号通道
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	// 等待信号
	sig := <-quit
	log.Info("Shutdown signal received", "", map[string]interface{}{
		"signal": sig.String(),
	})

	// 设置关闭超时
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 优雅关闭服务器
	log.Info("Shutting down server...", "", nil)
	if err := server.Shutdown(ctx); err != nil {
		log.Error("Server shutdown failed", "", map[string]interface{}{
			"error": err.Error(),
		})
	} else {
		log.Info("Server shutdown completed", "", nil)
	}
}
